"""
S8设备数据模型
S8 Device Data Models

定义S8设备的所有数据模型和验证规则
Defines all data models and validation rules for S8 devices
"""

from typing import Optional, Dict, Any, Union
from pydantic import BaseModel, Field, validator, root_validator
from datetime import datetime, timezone


class S8BaseData(BaseModel):
    """
    S8基础数据模型
    S8 Base Data Model
    
    所有S8数据的基础结构
    Base structure for all S8 data
    """
    device_id: Optional[str] = Field(None, description="设备唯一标识 / Device unique identifier")
    timestamp: Optional[int] = Field(None, description="时间戳 / Timestamp")

    class Config:
        extra = "allow"  # 允许额外字段 / Allow additional fields
        validate_assignment = True
        use_enum_values = True
    
    @validator('device_id', pre=True)
    def validate_device_id(cls, v):
        """验证设备ID格式 / Validate device ID format"""
        if v is None or v == "":
            return None
        
        if not isinstance(v, str):
            v = str(v)
        
        v = v.strip()
        
        if len(v) < 5:  # S8设备ID可能较短
            return None
        
        return v
    
    @validator('timestamp', pre=True)
    def validate_timestamp(cls, v):
        """验证时间戳合理性 / Validate timestamp reasonableness"""
        if v is None or v == 0 or v == "":
            return None
        
        if isinstance(v, str):
            try:
                v = int(v)
            except ValueError:
                return None
        
        if not isinstance(v, (int, float)):
            return None
        
        v = int(v)
        
        if v <= 0:
            return None
        
        # 检查时间戳是否在合理范围内 / Check if timestamp is in reasonable range
        min_timestamp = int(datetime(2020, 1, 1, tzinfo=timezone.utc).timestamp())
        max_timestamp = int(datetime(2050, 1, 1, tzinfo=timezone.utc).timestamp())
        
        if v < min_timestamp or v > max_timestamp:
            return None  # S8对时间戳更宽松，不合理时返回None
        
        return v


class S8LocationData(S8BaseData):
    """
    S8定位数据模型
    S8 Location Data Model
    
    处理S8设备的GPS定位信息
    Handles GPS location information from S8 devices
    """
    longitude: Optional[float] = Field(None, description="经度 / Longitude")
    latitude: Optional[float] = Field(None, description="纬度 / Latitude")
    location_type: Optional[str] = Field(None, description="定位类型 / Location type")
    accuracy: Optional[float] = Field(None, description="定位精度 / Location accuracy")
    
    @validator('longitude', pre=True)
    def validate_longitude(cls, v):
        """验证经度范围 / Validate longitude range"""
        if v is None or v == "" or v == 0:
            return None
        
        if isinstance(v, str):
            try:
                v = float(v)
            except ValueError:
                return None
        
        if not isinstance(v, (int, float)):
            return None
        
        v = float(v)
        
        if not -180 <= v <= 180:
            return None  # S8更宽松，超出范围返回None而不抛异常
        
        return v
    
    @validator('latitude', pre=True)
    def validate_latitude(cls, v):
        """验证纬度范围 / Validate latitude range"""
        if v is None or v == "" or v == 0:
            return None
        
        if isinstance(v, str):
            try:
                v = float(v)
            except ValueError:
                return None
        
        if not isinstance(v, (int, float)):
            return None
        
        v = float(v)
        
        if not -90 <= v <= 90:
            return None
        
        return v
    
    @validator('accuracy', pre=True)
    def validate_accuracy(cls, v):
        """验证定位精度 / Validate location accuracy"""
        if v is None:
            return None
        
        if isinstance(v, str):
            try:
                v = float(v)
            except ValueError:
                return None
        
        if not isinstance(v, (int, float)):
            return None
        
        v = float(v)
        
        # 精度不能为负数，设置合理上限
        if v < 0 or v > 10000:  # 10km精度上限
            return None
        
        return v


class S8HealthData(S8BaseData):
    """
    S8健康数据模型
    S8 Health Data Model
    
    处理S8设备的健康监测数据
    Handles health monitoring data from S8 devices
    """
    heart_rate: Optional[int] = Field(None, description="心率(次/分) / Heart rate (beats/min)")
    blood_oxygen: Optional[int] = Field(None, description="血氧饱和度(%) / Blood oxygen saturation (%)")
    body_temperature: Optional[float] = Field(None, description="体温(°C) / Body temperature (°C)")
    blood_pressure: Optional[str] = Field(None, description="血压数据 / Blood pressure data")
    steps: Optional[int] = Field(None, description="步数 / Step count")
    sleep_data: Optional[Dict[str, Any]] = Field(None, description="睡眠数据 / Sleep data")
    
    @validator('heart_rate', pre=True)
    def validate_heart_rate(cls, v):
        """验证心率数据 / Validate heart rate data"""
        if v is None or v == "" or v == 0:
            return None
        
        if isinstance(v, str):
            try:
                v = int(float(v))
            except ValueError:
                return None
        
        if not isinstance(v, (int, float)):
            return None
        
        v = int(v)
        
        if v < 0 or v > 500:
            return None
        
        return v
    
    @validator('blood_oxygen', pre=True)
    def validate_blood_oxygen(cls, v):
        """验证血氧数据 / Validate blood oxygen data"""
        if v is None or v == "" or v == 0:
            return None
        
        if isinstance(v, str):
            try:
                v = int(float(v))
            except ValueError:
                return None
        
        if not isinstance(v, (int, float)):
            return None
        
        v = int(v)
        
        if v < 0 or v > 100:
            return None
        
        return v
    
    @validator('body_temperature', pre=True)
    def validate_body_temperature(cls, v):
        """验证体温数据 / Validate body temperature data"""
        if v is None or v == "" or v == 0:
            return None
        
        if isinstance(v, str):
            try:
                v = float(v)
            except ValueError:
                return None
        
        if not isinstance(v, (int, float)):
            return None
        
        v = float(v)
        
        if v < 30.0 or v > 50.0:
            return None
        
        return v
    
    @validator('steps', pre=True)
    def validate_steps(cls, v):
        """验证步数数据 / Validate step count data"""
        if v is None or v == "":
            return None
        
        if isinstance(v, str):
            try:
                v = int(float(v))
            except ValueError:
                return None
        
        if not isinstance(v, (int, float)):
            return None
        
        v = int(v)
        
        if v < 0 or v > 200000:  # S8可能记录更长时间的步数
            return None
        
        return v
    
    @validator('blood_pressure', pre=True)
    def validate_blood_pressure_format(cls, v):
        """验证血压格式 / Validate blood pressure format"""
        if v is None or v == "":
            return None
        
        if not isinstance(v, str):
            v = str(v)
        
        v = v.strip()
        
        if not v:
            return None
        
        # 尝试解析血压格式 / Try to parse blood pressure format
        if '/' in v:
            try:
                parts = v.split('/')
                if len(parts) == 2:
                    high = int(float(parts[0]))
                    low = int(float(parts[1]))
                    
                    # 验证血压值的合理性 / Validate blood pressure values
                    if 50 <= high <= 300 and 30 <= low <= 200 and high > low:
                        return f"{high}/{low}"
            except (ValueError, IndexError):
                pass
        else:
            # 如果只有一个数字，尝试作为收缩压处理 / If only one number, treat as systolic
            try:
                pressure = int(float(v))
                if 50 <= pressure <= 300:
                    return str(pressure)
            except ValueError:
                pass
        
        return None  # 格式错误时返回None而不抛异常


class S8BatteryData(S8BaseData):
    """
    S8电池数据模型
    S8 Battery Data Model
    
    处理S8设备的电池状态信息
    Handles battery status information from S8 devices
    """
    battery_level: Optional[int] = Field(None, description="电池电量(%) / Battery level (%)")
    charging_status: Optional[bool] = Field(None, description="充电状态 / Charging status")
    power_mode: Optional[str] = Field(None, description="电源模式 / Power mode")
    
    @validator('battery_level', pre=True)
    def validate_battery_level(cls, v):
        """验证电池电量 / Validate battery level"""
        if v is None or v == "":
            return None
        
        if isinstance(v, str):
            try:
                v = int(float(v))
            except ValueError:
                return None
        
        if not isinstance(v, (int, float)):
            return None
        
        v = int(v)
        
        if v < 0:
            return 0
        if v > 100:
            return 100
        
        return v
    
    @validator('charging_status', pre=True)
    def validate_charging_status(cls, v):
        """验证充电状态 / Validate charging status"""
        if v is None or v == "":
            return None
        
        if isinstance(v, str):
            v_lower = v.lower().strip()
            if v_lower in ['true', '1', 'yes', 'on', 'charging']:
                return True
            elif v_lower in ['false', '0', 'no', 'off', 'not_charging']:
                return False
            else:
                return None
        
        if isinstance(v, (int, float)):
            return bool(v)
        
        if isinstance(v, bool):
            return v
        
        return None


class S8SensorData(S8BaseData):
    """
    S8传感器数据模型
    S8 Sensor Data Model
    
    处理S8设备的各种传感器数据
    Handles various sensor data from S8 devices
    """
    accelerometer: Optional[Dict[str, float]] = Field(None, description="加速度计数据 / Accelerometer data")
    gyroscope: Optional[Dict[str, float]] = Field(None, description="陀螺仪数据 / Gyroscope data")
    magnetometer: Optional[Dict[str, float]] = Field(None, description="磁力计数据 / Magnetometer data")
    ambient_light: Optional[float] = Field(None, description="环境光照度 / Ambient light intensity")
    pressure: Optional[float] = Field(None, description="大气压力 / Atmospheric pressure")


class S8AlertData(S8BaseData):
    """
    S8警报数据模型
    S8 Alert Data Model
    
    处理S8设备的各种警报信息
    Handles various alert information from S8 devices
    """
    alert_type: Optional[str] = Field(None, description="警报类型 / Alert type")
    alert_level: Optional[int] = Field(None, description="警报级别 / Alert level")
    
    @validator('alert_level', pre=True)
    def validate_alert_level(cls, v):
        """验证警报级别 / Validate alert level"""
        if v is None or v == "":
            return None
        
        if isinstance(v, str):
            try:
                v = int(v)
            except ValueError:
                return None
        
        if not isinstance(v, (int, float)):
            return None
        
        v = int(v)
        
        # 将级别限制在1-10之间，比原来更宽松
        if v < 1:
            return 1
        if v > 10:
            return 10
        
        return v
    alert_message: Optional[str] = Field(None, description="警报消息 / Alert message")
    location: Optional[Dict[str, float]] = Field(None, description="警报位置 / Alert location")


class S8DeviceStatus(S8BaseData):
    """
    S8设备状态模型
    S8 Device Status Model
    
    处理S8设备的状态信息
    Handles status information from S8 devices
    """
    firmware_version: Optional[str] = Field(None, description="固件版本 / Firmware version")
    hardware_version: Optional[str] = Field(None, description="硬件版本 / Hardware version")
    connection_status: Optional[str] = Field(None, description="连接状态 / Connection status")
    last_sync_time: Optional[int] = Field(None, description="最后同步时间 / Last sync time")
    memory_usage: Optional[float] = Field(None, description="内存使用率 / Memory usage")


class S8DataModels:
    """
    S8数据模型集合
    S8 Data Models Collection
    
    提供所有S8数据模型的统一访问接口
    Provides unified access interface for all S8 data models
    """
    
    # 数据模型映射表 / Data model mapping table
    MODEL_MAPPING = {
        "location": S8LocationData,
        "health": S8HealthData,
        "battery": S8BatteryData,
        "sensor": S8SensorData,
        "alert": S8AlertData,
        "status": S8DeviceStatus
    }
    
    @classmethod
    def get_model(cls, data_type: str) -> Optional[BaseModel]:
        """
        根据数据类型获取对应的数据模型
        Get corresponding data model based on data type
        
        Args:
            data_type (str): 数据类型 / Data type
            
        Returns:
            Optional[BaseModel]: 数据模型类 / Data model class
        """
        return cls.MODEL_MAPPING.get(data_type.lower())
    
    @classmethod
    def get_all_models(cls) -> Dict[str, BaseModel]:
        """
        获取所有数据模型
        Get all data models
        
        Returns:
            Dict[str, BaseModel]: 所有数据模型 / All data models
        """
        return cls.MODEL_MAPPING.copy()
    
    @classmethod
    def validate_data_type(cls, data_type: str) -> bool:
        """
        验证数据类型是否支持
        Validate if data type is supported
        
        Args:
            data_type (str): 数据类型 / Data type
            
        Returns:
            bool: 是否支持 / Whether supported
        """
        try:
            if not isinstance(data_type, str):
                return False
            return data_type.lower() in cls.MODEL_MAPPING
        except (AttributeError, TypeError):
            return False
    
    @classmethod
    def infer_data_type(cls, raw_data: Dict[str, Any]) -> Optional[str]:
        """
        根据原始数据推断数据类型
        Infer data type based on raw data
        
        Args:
            raw_data (Dict[str, Any]): 原始数据 / Raw data
            
        Returns:
            Optional[str]: 推断的数据类型 / Inferred data type
        """
        try:
            # 安全地检查数据结构 / Safely check data structure
            if not isinstance(raw_data, dict) or not raw_data:
                return None
            
            # 更严格的类型推断逻辑 / More strict type inference logic
            location_fields = ['longitude', 'latitude', 'coords', 'position']
            health_fields = ['heart_rate', 'blood_oxygen', 'body_temperature', 'blood_pressure', 'pulse']
            battery_fields = ['battery_level', 'battery', 'charging_status', 'power']
            sensor_fields = ['accelerometer', 'gyroscope', 'magnetometer', 'sensor_data']
            alert_fields = ['alert_type', 'alert_level', 'warning', 'alarm']
            status_fields = ['firmware_version', 'connection_status', 'device_status', 'system_info']
            
            # 计算匹配分数 / Calculate match scores
            scores = {
                'location': sum(1 for field in location_fields if field in raw_data),
                'health': sum(1 for field in health_fields if field in raw_data),
                'battery': sum(1 for field in battery_fields if field in raw_data),
                'sensor': sum(1 for field in sensor_fields if field in raw_data),
                'alert': sum(1 for field in alert_fields if field in raw_data),
                'status': sum(1 for field in status_fields if field in raw_data)
            }
            
            # 找到得分最高的类型 / Find the highest scoring type
            max_score = max(scores.values())
            if max_score > 0:
                for data_type, score in scores.items():
                    if score == max_score:
                        return data_type
            
            # 如果没有明确匹配，检查通用字段 / If no clear match, check common fields
            if any(key in raw_data for key in ['steps', 'distance', 'calories']):
                return 'health'
            
            return None
            
        except (AttributeError, TypeError, KeyError) as e:
            # 记录错误但不抛出异常 / Log error but don't raise exception
            return None